/*
 * @Description: 
 * @Date: 2021-08-24 09:15:01
 * @Author: 刘元峰
 * @LastEditTime : 2021-08-26 09:53:22
 * @LastEditors  : 保锋
 * @FilePath     : \flutter_demo\lib\widgets\floating_icon.dart
 */

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

///悬浮按钮
///
///[imgUrl]图片地址默认为'assets/images/home/在线客服.png'
///
///[width]图片宽度，默认为120.w
///
///[height]图片高度，默认为120.w
///
///[left]图片高度，默认为null
///
///[right]图片高度，默认为0
///
///[top]图片高度，默认为null
///
///[bottom]图片高度，默认为400.h
///
///[onTap]点击事件
class FloatingIcon extends StatefulWidget {
  const FloatingIcon(
      {Key? key,
      this.imgUrl = 'assets/images/home/在线客服.png',
      this.width,
      this.height,
      this.left,
      this.right,
      this.top,
      this.bottom,
      this.onTap})
      : assert(left == null || right == null || width == null),
        assert(top == null || bottom == null || height == null),
        super(key: key);

  ///图片地址
  final String imgUrl;

  ///图片宽度
  final double? width;

  ///图片高度
  final double? height;

  ///距离左边的位置
  final double? left;

  ///距离上边的位置
  final double? top;

  ///距离下边的位置
  final double? bottom;

  ///距离右边的位置
  final double? right;

  ///点击的回调
  final void Function()? onTap;
  @override
  _FloatingIconState createState() => _FloatingIconState();
}

class _FloatingIconState extends State<FloatingIcon> {
  final FloatingIconController vm = Get.put(FloatingIconController());

  ///组件宽度
  late final double width;

  ///组件高度
  late final double height;

  ///组件横坐标
  late double left;

  ///组件纵坐标（含拖拽中）
  late double top;

  ///拖拽结束以后吸边的横坐标
  late double leftEnd;

  ///横坐标差值修正
  double leftFixed = 0.0;

  ///纵坐标差值修正
  double topFixed = 0.0;

  ///拖拽过程标识,true为拖拽中,false为没有拖拽
  bool isdrag = false;
  @override
  void initState() {
    initSizeAndPosition();
    super.initState();
  }

  ///初始化组件的大小和位置
  void initSizeAndPosition() {
    width = widget.width ?? 120.w;
    height = widget.height ?? 120.w;

    if (widget.left == null) {
      if (widget.right == null) {
        left = 1.sw - 0 - width;
      } else {
        left = 1.sw - widget.right! - width;
      }
    } else {
      left = widget.left!;
    }
    leftEnd = left;
    if (widget.top == null) {
      if (widget.bottom == null) {
        top = 1.sh - 400.h - height;
      } else {
        top = 1.sh - widget.bottom! - height;
      }
    } else {
      top = widget.top!;
    }
  }

  @override
  Widget build(BuildContext context) {
    return GetBuilder<FloatingIconController>(
        id: 'dr',
        builder: (_) {
          /// 1.当拖拽结束后，手动刷新dr视图，重启动画效果，以达到吸边的效果
          return TweenAnimationBuilder<double>(
            key: UniqueKey(),
            curve: Curves.easeOutBack,
            tween: Tween<double>(begin: left, end: leftEnd),
            duration: const Duration(milliseconds: 800),
            builder: (BuildContext context, double value, Widget? child) {
              ///2.从拖拽中结束的坐标位置，不断向靠近组件的一边的坐标不断变化(动画效果left-->leftEnd)
              return GetBuilder<FloatingIconController>(
                  id: 'po',
                  builder: (_) {
                    ///3.拖拽中，不断手动刷新po视图，变更组件位置，以实现拖拽效果
                    return Positioned(
                        top: top,
                        left: isdrag ? left : value,
                        child: GestureDetector(
                          ///3.1拖拽开始时，记录组件横坐标与纵坐标的修正值
                          onPanStart: (DragStartDetails e) {
                            leftFixed = e.globalPosition.dx - left;
                            topFixed = e.globalPosition.dy - top;
                            isdrag = true;
                          },

                          ///3.2 限制组件在移动时的区域（屏幕内），防止越出手机屏幕，并更新left与top的值
                          onPanUpdate: (DragUpdateDetails e) {
                            left = e.globalPosition.dx - leftFixed;
                            top = e.globalPosition.dy - topFixed;
                            if (left + width > 1.sw) {
                              left = 1.sw - width;
                            }
                            if (left <= 0) {
                              left = 0;
                            }
                            if (top <= 0) {
                              top = 0;
                            }
                            if (top + width > 1.sh) {
                              top = 1.sh - width;
                            }
                            _.update(<String>['po']);
                          },

                          ///3.3 拖动结束，left为拖拽停止时的浮动窗位置。leftEnd为浮动窗最终吸边停止的位置。

                          onPanEnd: (DragEndDetails e) {
                            if ((left + width / 2) < (1.sw / 2)) {
                              leftEnd = 0.w;
                              _.update(<String>['dr']);

                              ///延迟修正left的位置，不然会出现动画错误
                              Future<void>.delayed(
                                  const Duration(milliseconds: 50), () {
                                left = 0.w;
                              });
                            } else {
                              leftEnd = 1.sw - width;
                              _.update(<String>['dr']);

                              ///延迟修正left的位置，不然会出现动画错误
                              Future<void>.delayed(
                                  const Duration(milliseconds: 50), () {
                                left = 1.sw - width;
                              });
                            }
                            isdrag = false;
                          },
                          onTap: widget.onTap ??
                              () {
                                print('点击了');
                              },
                          child: Image.asset(
                            widget.imgUrl,
                            width: width,
                            height: height,
                          ),
                        ));
                  });
            },
          );
        });
  }
}

class FloatingIconController extends GetxController {}
